<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>08-迭代对象-自定义类的迭代</title>
  <!-- 
  在 JavaScript 中，自定义类的迭代可以通过实现  `Symbol.iterator`  方法来实现。这使得自定义对象能够像内置的可迭代对象（如数组、字符串等）一样被遍历。
  1. 实现  `Symbol.iterator`  方法

  要使自定义类成为可迭代对象，需要在类中实现  `Symbol.iterator`  方法。该方法应该返回一个迭代器对象，该对象必须实现  `next()`  方法。

  2. 迭代器对象

  迭代器对象的  `next()`  方法应该返回一个包含两个属性的对象：
  -  `value` : 当前迭代的值。
  -  `done` : 一个布尔值，表示迭代是否完成。

  3. 示例代码

  以下是一个自定义类的示例，展示了如何实现可迭代对象：
  class MyCollection {
      constructor() {
          this.items = [];
      }

      add(item) {
          this.items.push(item);
      }

      // 实现 Symbol.iterator 方法
      [Symbol.iterator]() {
          let index = 0; // 当前索引
          const items = this.items; // 引用当前集合的项

          // 返回一个迭代器对象
          return {
              next() {
                  if (index < items.length) {
                      return { value: items[index++], done: false }; // 返回当前值和未完成状态
                  }
                  return { done: true }; // 迭代完成
              }
          };
      }
  }

  // 使用自定义类
  const collection = new MyCollection();
  collection.add(1);
  collection.add(2);
  collection.add(3);

  // 使用 for...of 循环遍历自定义集合
  for (const item of collection) {
      console.log(item); // 输出 1, 2, 3
  }
  4. 注意事项

  - 状态管理：在迭代器中管理状态（如当前索引）是关键。确保在  `next()`  方法中正确更新状态。
  - 可重用性：每次调用  `Symbol.iterator`  方法时，都会返回一个新的迭代器实例。这意味着可以多次迭代同一个集合，而不会干扰其他迭代。
  - 支持其他方法：可以在自定义类中添加其他方法，以便更灵活地操作集合，例如删除项、查找项等。

  5. 总结

  通过实现  `Symbol.iterator`  方法，自定义类可以轻松地成为可迭代对象。这种能力使得自定义数据结构的使用更加灵活，能够与 JavaScript 的许多内置功能（如  `for...of`  循环、展开运算符等）无缝集成。
  -->
</head>
<body>

  <script>
    class Person {
      constructor(name, age, friends) {
        this.name = name;
        this.age = age;
        this.friends = friends;
      }

      // 实例方法 自定义类的迭代器
      [Symbol.iterator]() {
        let index = 0;
        let arr = Object.values(this);
        return {
          next: () => {
            if (index < arr.length) {
              return {
                value: arr[index++],
                done: false
              }
            } else {
              return {
                value: undefined,
                done: true
              }
            }
          }
        }
      }
    }

    const p = new Person('张三', 18, ['李四', '王五']);
    for (const item of p) {
      console.log(item);
    }

  </script>
  
</body>
</html>